/* Copyright (c) 2023 Renmin University of China
RMDB is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
        http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

#include <cstring>
#include "log_manager.h"

std::atomic<bool> enable_logging;
std::chrono::duration<int64_t> log_timeout = std::chrono::seconds(3);

/**
 * @brief 添加日志记录到日志缓冲区中，并返回日志记录号
 * @param {LogRecord*} log_record 要写入缓冲区的日志记录
 * @return {lsn_t} 返回该日志的日志记录号
 */
lsn_t LogManager::add_log_to_buffer(LogRecord* log_record) {
    // 判断缓冲区是否已满
    if (log_buffer_.is_full(log_record->log_tot_len_)) {
        // 如果缓冲区已满，则需要将缓冲区的内容刷到磁盘中
        flush_log_to_disk();
    }
    std::scoped_lock lock{latch_};
    // 分发日志记录号
    log_record->lsn_ = global_lsn_++;
    // 将日志记录添加到缓冲区中
    log_buffer_.append_log(log_record);
    return log_record->lsn_;
}


/**
 * @brief 把日志缓冲区的内容刷到磁盘中，由于目前只设置了一个缓冲区，因此需要阻塞其他日志操作
 */
void LogManager::flush_log_to_disk() {
    std::scoped_lock lock{latch_};
    // 将缓冲区的内容写入磁盘
    disk_manager_->write_log(log_buffer_.get_data(), log_buffer_.get_size());
    // 清空缓冲区
    log_buffer_.reset();
    // 更新最后一个日志记录的日志记录号
    persist_lsn_ = global_lsn_ - 1;
}
/**
 * @brief 隔一段时间log_timeout将日志缓冲区的内容刷到磁盘中
 * 
 */
void LogManager::run_flush_thread() {
    while (enable_logging) {
        std::unique_lock lock(flush_latch_);
        cv_.wait_for(lock, log_timeout, [&] { return need_flush(); });
        flush_log_to_disk();
        need_flush_ = false;
    }
}
